﻿using System;
#if WINDOWS_PHONE
using StyleMVVM.Data.Collections;
#else
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Utilities;

#if !DOT_NET
using Windows.Foundation;

#endif

namespace StyleMVVM.Logging
{
	public sealed class HoldingQueueAdapter : ILogAppender
	{
		private object lockObject = new object();
		private volatile bool closed = false;
		private volatile bool transferingQueue;
		private Action<ILogAppender> swapAdaptersMethod;

		public HoldingQueueAdapter()
		{
			holdQueue = true;
		}

		internal ConcurrentQueue<LogEntry> PendingMessages
		{
			get { return pendingMessages; }
		}

		private int maxProcessAtOneTime = 1000;
		private volatile bool holdQueue = false;
		private int queueDepth = 10;
		private readonly object outputLock = new object();
		private readonly ConcurrentQueue<LogEntry> pendingMessages = new ConcurrentQueue<LogEntry>();

		public int QueueDepth
		{
			get { return queueDepth; }
			set { queueDepth = value; }
		}

#if NETFX_CORE
		public IAsyncOperation<bool> Configure()
		{
			return AsyncHelper.ReturnAsyncOp(true);
		}
#else
		public Task<bool> Configure()
		{
			return TaskHelper.ReturnTask(true);
		}
#endif

		public void Flush()
		{
		}

		public LogLevel LoggingLevel { get; set; }

		public void Log(LogEntry entry)
		{
			if (entry.Level >= LoggingLevel)
			{
				pendingMessages.Enqueue(entry);

				if (pendingMessages.Count > QueueDepth && !holdQueue)
				{
					Task.Run(() => InternalLog(entry));
				}
			}
		}

		private async void InternalLog(LogEntry entry)
		{
			try
			{
				await RequestProcessQueue();
			}
			catch (Exception)
			{
			}
		}

		private async Task RequestProcessQueue()
		{
			bool outputThread = false;

			lock (outputLock)
			{
				if (!holdQueue)
				{
					holdQueue = true;
					outputThread = true;
				}
			}

			if (outputThread)
			{
				LogEntry output;
				List<LogEntry> entries = new List<LogEntry>();

				for (int i = 0; i < maxProcessAtOneTime; i++)
				{
					if (pendingMessages.TryDequeue(out output))
					{
						entries.Add(output);
					}
					else
					{
						break;
					}
				}

				await ProcessQueue(entries);

				holdQueue = false;

				if (pendingMessages.Count > queueDepth)
				{
					await RequestProcessQueue();
				}
			}
		}

		private async Task ProcessQueue(IEnumerable<LogEntry> entries)
		{
		}
	}
}